using Application.Service.LogCache;

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

using System.Diagnostics.CodeAnalysis;

namespace Application.Web.Entry.Shared
{
	public partial class LogDrawer : IAsyncDisposable
	{
		[Parameter]
		public string Height { get; set; } = "auto";
		
		[Inject] public LogCacheService LogCacheService { get; set; } = default!;
		[Inject] private IJSRuntime JSRuntime { get; set; } = default!;

		[NotNull]
		private List<LogEntry> logs { get; set; } = new List<LogEntry>();
		private IJSObjectReference? module;
		
		// 用于按钮定位的状态变量
		private bool isButtonFixed = false;
		private string buttonPositionStyle = "";

		protected override async Task OnAfterRenderAsync(bool firstRender)
		{
			if (firstRender)
			{
				// 初始化Bootstrap tooltip
				module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./js/tooltip.js");
				await module.InvokeVoidAsync("initTooltips");
				
				// 初始设置按钮位置
				await UpdateButtonPosition();
			}
		}

		protected override void OnInitialized()
		{
			// 加载现有日志
			logs = LogCacheService.GetLogs();

			// 订阅日志添加事件
			LogCacheService.OnLogAdded += OnLogAdded;
		}

		private async void OnLogAdded(LogEntry logEntry)
		{
			// 添加新日志到列表
			logs.Insert(0, logEntry); // 新日志显示在最上面

			// 如果日志数量超过200条，移除最旧的
			if (logs.Count > 200)
			{
				logs = logs.Take(200).ToList();
			}

			// 刷新UI并更新按钮位置
			await InvokeAsync(async () =>
			{
				StateHasChanged();
				await UpdateButtonPosition();
			});
		}

		private void ClearLogs()
		{
			LogWrapper.Clear();
			logs.Clear();
			StateHasChanged();
		}
		
		private async Task UpdateButtonPosition()
		{
			if (logs.Any())
			{
				try
				{
					// 获取Drawer容器的实际高度，让按钮始终固定在Drawer中间
					var jsCode = @"
						var drawer = document.querySelector('.drawer-body');
						if (drawer) {
							var drawerHeight = drawer.clientHeight;
							// 始终返回true，让按钮固定在中间位置
							return true;
						}
						return false;
					";
					
					var result = await JSRuntime.InvokeAsync<bool>("eval", jsCode);
					isButtonFixed = result;
					
					// 始终使用固定定位在中间位置
					buttonPositionStyle = "position: fixed; top: 50%; right: 20px; transform: translateY(-50%); z-index: 1000;";
					
					StateHasChanged();
				}
				catch (Exception ex)
				{
					// 如果JavaScript调用失败，使用固定位置在中间
					isButtonFixed = true;
					buttonPositionStyle = "position: fixed; top: 50%; right: 20px; transform: translateY(-50%); z-index: 1000;";
					StateHasChanged();
				}
			}
		}
		
		[JSInvokable]
		public IJSRuntime GetJSObject()
		{
			return JSRuntime;
		}

		private string GetLogLevelClass(Service.LogCache.LogLevel level)
		{
			return level switch
			{
				Service.LogCache.LogLevel.Trace => "log-trace",
				Service.LogCache.LogLevel.Debug => "log-debug",
				Service.LogCache.LogLevel.Information => "log-information",
				Service.LogCache.LogLevel.Warning => "log-warning",
				Service.LogCache.LogLevel.Error => "log-error",
				Service.LogCache.LogLevel.Critical => "log-critical",
				_ => "log-information"
			};
		}

		//private string GetLogLevelClass(string level)
		//{
		//	return level?.ToLower() switch
		//	{
		//		"info" => "info",
		//		"warn" => "warn",
		//		"error" => "error",
		//		"debug" => "debug",
		//		"trace" => "trace",
		//		_ => ""
		//	};
		//}

		private string TruncateMessage(string message)
		{
			// 估算最大字符数，实际可根据窗口宽度动态调整
			const int maxLen = 60;
			if (string.IsNullOrEmpty(message)) return "";
			return message.Length > maxLen ? message.Substring(0, maxLen - 3) + "..." : message;
		}

		private async Task ShowTooltip(string elementId, string message)
		{
			// 只有当消息被截断时才显示tooltip
			if (message.Length > 60 && module != null)
			{
				await module.InvokeVoidAsync("showTooltip", elementId, message);
			}
		}

		private async Task HideTooltip(string elementId)
		{
			if (module != null)
			{
				await module.InvokeVoidAsync("hideTooltip", elementId);
			}
		}

		public void Dispose()
		{
			LogCacheService.OnLogAdded -= OnLogAdded;
		}

		public async ValueTask DisposeAsync()
		{
			if (module != null)
			{
				try
				{
					await module.DisposeAsync();
				}
				catch (Microsoft.JSInterop.JSDisconnectedException)
				{
					// 忽略JS断开连接异常，这是正常的行为
					/* 
					确保在组件销毁时不会因为JavaScript互操作断开连接而抛出异常，这是Blazor应用中处理组件销毁的标准做法。
					- 1.异常捕获 ：使用 try-catch 块捕获 JSDisconnectedException 异常
					- 2.安全处理 ：当JavaScript互操作无法完成时，安全地忽略该异常
					- 3.保持功能 ：所有其他功能保持不变，包括tooltip显示和日志管理
					*/
				}
			}
		}
	}
}
